
var comments = {};
var enabled = true;
var disabledUsers = {};

User = (function (){
	var user = {};
	
	function init(){
		chrome.storage.sync.get(["user"], function(data){
			if (!data || !data.user){
				data = {user: {}};
			}
			if (data.user.id){
				user.id = data.user.id;
			} else{
				user.id = Utils.getRandomId("UID");
			}
			if (data.user.name){
				user.name = data.user.name;
			}
			else{
				user.name = "new user";
			}
			if (data.user.color){
				user.color = data.user.color;
			}
			else{
				user.color = "yellow";
			}
			chrome.storage.sync.set({user: user});
		});
	}

	
	function get(){
		return user;
	}
	
	function set(data){
		if (data.name){
			user.name = data.name;
		}
		if (data.color){
			user.color = data.color;
		}
		chrome.storage.sync.set({user: user});
	}
	
	return {
		init: init,
		set: set, 
		get: get
	}
})();

Icon = (function (){
	
	function change(imageUrl, callback){
		var details = {path: imageUrl};
		chrome.browserAction.setIcon(details, callback || function (){});
	}
	
	function disable(){
		change("images/disabled_19.png");
	}
	
	function enable(){
		change("images/comment_19.png");
	}

	
	return{
		disable: disable,
		enable: enable
	}
})();

var ServerData = (function(){
	var BASE_URL = "http://shareacomments.appspot.com/";
	//var BASE_URL = "http://127.0.0.1:8888/";
	
	function getParams(data){
		var params="";
		for (var param in data){
			var paramStr = (typeof data[param] == 'string') ? data[param] : encodeURIComponent(JSON.stringify(data[param])) ;
			params += param+"="+paramStr+"&";
		}
		return params.substring(0,params.length-1) //remove last &
	}
	
	function sendData(url,data,callback){
		
		var params = getParams(data);
		var http = new XMLHttpRequest();
		http.open("POST", BASE_URL + url, true);
		//Send the proper header information along with the request
		http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		http.onreadystatechange = function() {//Call a function when the state changes.
			if(http.readyState == 4 && http.status == 200) {
				callback(http.responseText);
			}
		}
		http.send(params);
	}
	
	function getData(url,data,callback){
		var http = new XMLHttpRequest();
		url = BASE_URL + url + "?" + getParams(data);
		http.open("GET", url, true);
		http.onreadystatechange = function() {//Call a function when the state changes.
			if(http.readyState == 4 && http.status == 200) {
				callback(http.responseText);
			}
		}
		http.send(null);
		
	}
	
	function addComment(comment, commentUrl){
		sendData("shareComments",{comment: comment, commentUrl: commentUrl, UID: User.get().id},function(){})
	}
	
	function getComments(commentUrl, callback){
		getData("shareComments", {commentUrl: commentUrl, UID: User.get().id}, callback)
	}
	
	return {
		addComment: addComment,
		getComments: getComments
	}
})();
var Comments = (function(){
	
	function pushToList(url, commentsList){
		if (commentsList){
			for (var j=0; j< commentsList.length; j++){
				if (commentsList[j] && commentsList[j].commentId){
					if (!comments[url]) {
						comments[url] = {list: []};
					}
					var commentExist = false;
					for (var i=0; i< comments[url].list.length; i++){
						if (comments[url].list[i].commentId == commentsList[j].commentId){
							//comment already exist in client
							commentExist = true;
						}
					}
					if (!commentExist){
						comments[url].list.push(commentsList[j]);
					}
					
				}
			}
		}
	}
	
	function disableUsers(url, users){
		if (!disabledUsers[url]) {
			disabledUsers[url] = {};
		}
		for (var user in users){
			disabledUsers[url][user] = users[user];
		}
		
	}
	function add(data, sender) {
		var commentData = {
			firstId : data.firstId,
			parentType : data.parentType,
			elemIndex: data.elemIndex,
			text : data.text,
			comment: data.comment,
			userId: User.get().id,
			userName: User.get().name,
			commentId: Utils.getRandomId("CID")
		}
		pushToList(data.url,[commentData]);
		ServerData.addComment(commentData, data.url);
	}
	
	function filterDisabledUsers(commentList, filter){
		var filteredComments = [];
		for (var i=0; i< commentList.length; i++){
			var disabledUser = filter && filter[commentList[i].userId];
			if (!disabledUser){
				filteredComments.push(commentList[i]);
			}
		}
		return filteredComments;
	}
	
	function get(url, callback){
		ServerData.getComments(url, function(sComments){
			try{
				var serverComments = JSON.parse(sComments);
				pushToList(url, serverComments);
			} catch(e){}
			var filteredComments = [];
			if (comments[url]){
				filteredComments = filterDisabledUsers(comments[url].list, disabledUsers[url]);
			}
			callback({list: filteredComments, color: User.get().color});
		});
		//callback(comments[url]);
	}
	
	function getList(url){
		if (comments[url]){
			return comments[url].list
		}
		return [];
	}
	
	return {
		add: add,
		get: get,
		getList: getList,
		disableUsers: disableUsers
	}
})();

var Utils = (function(){
	
	function getRandomId(prefix){
		prefix = prefix || "";
		return prefix + (Math.random().toString().split(".")[1]);
	}
	
	function getUsersList(url){
		var usersList = [];
		var existUsers = {}
		existUsers[User.get().id] = true;
		if (comments[url]){
			for (var i=0; i< comments[url].list.length; i++){
				comment = comments[url].list[i];
				if (!existUsers[comment.userId]){
					existUsers[comment.userId] = true;
					var disabledUser = disabledUsers[url] && disabledUsers[url][comment.userId];
					usersList.push({name:comment.userName, id:comment.userId, disabled: disabledUser});
				}
			}
		}
		return usersList;
	}
	
	
	return {
		getRandomId: getRandomId,
		getUsersList: getUsersList
	}
})();

var Page = (function(){
	
	function disable(tab, callback){
		chrome.tabs.executeScript(tab.id, {code: "disable("+JSON.stringify(Comments.getList(tab.url))+")"}, callback);
	}
	
	function enable(tab, callback){
		Comments.get(tab.url, function(commentsObj){
			chrome.tabs.executeScript(tab.id, {code: "enable("+JSON.stringify(commentsObj.list)+")"}, callback);
		});
		
	}
	function updateComments(tab, callback){
		disable(tab, function(){
			enable(tab, callback);
		})
	}

	function changeCommentColor(tab, newColor){
		chrome.tabs.insertCSS(tab.id, {code :".comment_color{ background-color:"+ newColor +" !important}"});
	
	}
	
	return {
		disable: disable,
		enable: enable,
		updateComments: updateComments,
		changeCommentColor: changeCommentColor
	}
})();

var MessageHandler = (function(){
	var popupCurrentTab;
	
	function addComment(data, sender) {
		if (data){
			Comments.add(data, sender);
		}
	}
	
	function getComments(url, sender, callback){
		if (enabled && url){
			Comments.get(url, callback);
		}else{
			callback({disabled: true});
		}
	}
	
	function disable(data, sender){
		enabled = false;
		Icon.disable();
		chrome.storage.local.set({enabled: enabled});
		Page.disable(popupCurrentTab);
	}
	
	function enable(data, sender){
		enabled = true;
		Icon.enable();
		chrome.storage.local.set({enabled: enabled});
		Page.enable(popupCurrentTab);
	}
	function isEnabled(data, sender, callback){
		callback(enabled);
	}
	function getUser(data, sender, callback){
		callback(User.get());
	}
	function updateUser(data, sender){
		User.set(data);
		if (data.color){
			Page.changeCommentColor(popupCurrentTab, User.get().color)
		}
	}
	function getTabUsersList(data, sender, callback){
		chrome.tabs.query({active: true},function(tabs){
			popupCurrentTab = tabs[0];
			callback(Utils.getUsersList(tabs[0].url));
		});
	}
	function disableTabUsers(data){
		if (data){
			Comments.disableUsers(popupCurrentTab.url, data);
			Page.updateComments(popupCurrentTab);
		}
	}
	return{
		addComment: addComment,
		getComments: getComments,
		disable: disable,
		enable: enable,
		isEnabled: isEnabled,
		getUser: getUser,
		updateUser: updateUser,
		getTabUsersList: getTabUsersList,
		disableTabUsers: disableTabUsers	
	}
})();

function init(){
	User.init();
	chrome.storage.local.get("enabled", function(data){
		if (data && typeof data.enabled != 'undefined'){
			enabled = data.enabled;
			if (data.enabled == false){
				Icon.disable();
			}
		} else{
			enabled = true;
		}

	});
	
	chrome.extension.onMessage.addListener(function (message, sender, callback) {
		if (message.type) {
			MessageHandler[message.type] && MessageHandler[message.type](message.data, sender,callback);
		}
		return true;
	});
}

init();